/*
 * ListaInvertida.cpp
 *
 *  Created on: Nov 13, 2013
 *      Author: damian
 */

#include <algorithm>
#include "ListaInvertida.h"

using std::transform;

vector<string> ListaInvertida::stopWords;  // con esto se la declara en el stack

ListaInvertida::ListaInvertida(string ruta_archivo, int maxTamanioClave, string ruta_stopwords) {
	indiceInvertido = new ArbolBMas(ruta_archivo, maxTamanioClave);

	if(stopWords.empty()) {
		std::ifstream archivo(ruta_stopwords.c_str(), std::ios::in);
		if(archivo) {
			while(!archivo.eof()) {
				string linea;
				getline(archivo, linea);
				if (linea.size() > 0) {
					stopWords.push_back(linea);
				}
			}
			archivo.close();
		}
		else
			cout << "El archivo de stopWords no existe" << endl;
	}

	idBase = 0;
}

ListaInvertida::~ListaInvertida() {
	delete indiceInvertido;
}

void ListaInvertida::extraerTerminos(string texto, int regId){
	normalizar(&texto);
	int id = regId-idBase;
	vector<string> palabras;
	Utilitarios::split(texto, " ", &palabras);
	for(int j=0; j < (int)palabras.size(); j++){
		if(!esStopWord(palabras[j])){
			Clave* clave = new Clave(palabras[j]);
			RegistroArbol* reg = indiceInvertido->buscar(*clave);
			if(!reg->getClave()->getClave().empty()){
				CadenaBytes* cadenaIds = reg->getDatos();
				string ids = cadenaIds->toString();
				ids = ids + "," + Utilitarios::intToString(id);
				CadenaBytes* cadena = new CadenaBytes(ids);
				RegistroArbol* registro = new RegistroArbol(clave, cadena);
				indiceInvertido->modificar(registro);
			}
			else{
				string palabra = palabras[j];
				if(palabra.size() <= 1)
					continue;
				Clave* clave = new Clave(palabra);
				CadenaBytes* cadena = new CadenaBytes(Utilitarios::intToString(id));
				RegistroArbol* registro = new RegistroArbol(clave, cadena);
				indiceInvertido->insertar(registro);
			}
		}
	}
}

bool ListaInvertida::buscar(string termino, vector<int>* regIds) {
	normalizar(&termino);
	Clave clave = Clave(termino);
	RegistroArbol* registro = indiceInvertido->buscar(clave);
	if(registro != 0) {
		CadenaBytes* cadena = registro->getDatos();
		string valores = cadena->toString();
		//cout << "valores " + valores << endl;
		vector<string> ids;
		Utilitarios::split(valores, ",", &ids);
		for(int i=0; i < (int)ids.size(); i++)
			regIds->push_back(idBase+Utilitarios::stringToInt(ids[i]));
		return !ids.empty();
	}
	return false;
}

void ListaInvertida::setIdBase(unsigned int idBase) {
	this->idBase = idBase;
}

void ListaInvertida::normalizar(string* texto) {
	transform(texto->begin(), texto->end(), texto->begin(), ::tolower);
}

bool ListaInvertida::esStopWord(string palabra){
	return std::find(stopWords.begin(), stopWords.end(), palabra) != stopWords.end();
}
